/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
package org.epic.perleditor.templates.textmanipulation;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.CoreException;


public class MultiTextEdit {

    private List<Object> fChildren;

    /**
     * Creates a new composite text edit.
     */
    public MultiTextEdit() {
        fChildren= new ArrayList<Object>(3);
    }

    protected MultiTextEdit(List<Object> children) throws CoreException {
        fChildren= new ArrayList<Object>(children.size());
        for (Iterator<Object> iter= children.iterator(); iter.hasNext();) {
            fChildren.add(((TextEdit)iter.next()).copy());
        }
    }
    
    protected List<Object> getChildren() {
        return fChildren;
    }
    
    /**
     * Adds all <code>TextEdits</code> managed by the given multt text edit.
     * 
     * @param edit the multi text edit to be added.
     */
    public void add(MultiTextEdit edit) {
        assert edit != null;
        fChildren.add(edit);
    }
    
    /**
     * Adds a text edit.
     * 
     * @param edit the text edit to be added
     */
    public void add(TextEdit edit) {
        assert edit != null;
        fChildren.add(edit);
    }
    
    /**
     * Returns the children managed by this text edit collection.
     * 
     * @return the children of this composite text edit
     */
    public Iterator<Object> iterator() {
        return fChildren.iterator();
    }

    /**
     * Connects this text edit to the given <code>TextBufferEditor</code>. 
     * Note that this method <b>should only be called</b> by a <code>
     * TextBufferEditor</code>.
     *<p>
     * This default implementation does nothing. Subclasses may override
     * if needed.
     *  
     * @param editor the text buffer editor this text edit has been added to
     */
    public void connect(TextBufferEditor editor) throws CoreException {
        for (Iterator<Object> iter= fChildren.iterator(); iter.hasNext();) {
            Object element= iter.next();
            if (element instanceof TextEdit)
                editor.add((TextEdit)element);
            else
                editor.add((MultiTextEdit)element);
        }
    }
    
    /**
     * Creates and returns a copy of this text edit collection. The copy method should
     * be implemented in a way so that the copy can be added to a different  <code>
     * TextBuffer</code> without causing any harm to the object from which the copy 
     * has been created.
     * 
     * @return a copy of this object.
     */
    public MultiTextEdit copy() throws CoreException {
        return new MultiTextEdit(fChildren);
    }
    
    /**
     * Returns the <code>TextRange</code> that this text edit is going to
     * manipulate. If this method is called before the <code>MultiTextEdit</code>
     * has been added to a <code>TextBufferEditor</code> it may return <code>
     * null</code> to indicate this situation.
     * 
     * @return the <code>TextRange</code>s this <code>TextEdit is going
     * 	to manipulate
     */
    public TextRange getTextRange() {
        int size= fChildren.size();
        if (size == 0)
            return new TextRange(0,0);
        TextRange range= ((TextEdit)fChildren.get(0)).getTextRange();
        int start= range.getOffset();
        int end= range.getInclusiveEnd();
        for (int i= 1; i < size; i++) {
            range= ((TextEdit)fChildren.get(i)).getTextRange();
            start= Math.min(start, range.getOffset());
            end= Math.max(end, range.getInclusiveEnd());
        }
        return new TextRange(start, end - start + 1);
    }
    
    /**
     * Returns the element modified by this text edit. The method
     * may return <code>null</code> if the modification isn't related to a
     * element or if the content of the modified text buffer doesn't
     * follow any syntax.
     * <p>
     * This default implementation returns <code>null</code>
     * 
     * @return the element modified by this text edit
     */
    public Object getModifiedElement() {
        return null;
    }	
}

